//package declaration
package pxgrid_servlets;

//imports
import com.oreilly.servlet.*;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import pxgrid_controllers.*;
import pxgrid_utils.*;

/**
 * PXSubmitServlet
 * A servlet to process job submission and send it off to the PXSubmissionController
 * 
 * @author Mark Bate
 */
public class PXSubmitServlet extends HttpServlet {

    private PXSubmissionController submissionController;
    private Boolean debug = false;

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException
     * @throws IOException 
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {

            //The submission id to access this job
            String submission_id = null;

            //get a timestamp & append to end of tmp.
            String timestamp = String.valueOf(System.currentTimeMillis());
            String pdbs_temp_dir = PXUtils.getDataStoreFromServerConfigXML() + "/tmp" + timestamp;

            //create the folders
            File tempDir = new File(pdbs_temp_dir);
            tempDir.mkdirs();


            //grab the form as a mutlipart request
            MultipartRequest multi = new MultipartRequest(request, pdbs_temp_dir, 20 * 1024 * 1024); // 10MB limit
   
            //try creating a new PXSubmissionController, if we can't redirect
            //to the error page
            try {
                this.submissionController = new PXSubmissionController(this.debug);
            } catch (Exception ex) {
                out.println("<html>");
                out.println("<meta http-equiv=\"refresh\" content=\"0; url=error.jsp?errorcode=6\">");
                out.println("</html>");
            }

            //set the MTZFile
            String mtz_file = multi.getParameter("MTZFile_uploaded").trim();
            String mtz_temp_dir = multi.getParameter("tmpDir").trim();

            //check it exists
            File mtz_file_test = new File(mtz_temp_dir + "/" + mtz_file);
            if (!mtz_file_test.isFile()) {

                //file doesn't exist go to an error page.
                out.println("<html>");
                out.println("<meta http-equiv=\"refresh\" content=\"0; url=error.jsp?errorcode=5\">");
                out.println("</html>");

            } else {
                //file exists, go on...

                //set the PDBFile
                String pdb_file = multi.getFilesystemName("PDBTar");
                //check it exists
                File pdb_file_test = new File(pdbs_temp_dir + "/" + pdb_file);
                if (!pdb_file_test.exists()) {

                    //file doesn't exist go to an error page.
                    out.println("<html>");
                    out.println("<meta http-equiv=\"refresh\" content=\"0; url=error.jsp?errorcode=3\">");
                    out.println("</html>");

                } else {

                    //file exists, keep going...
                    
                    //get the mime_type of the archive
                    String mime_type = multi.getContentType("PDBTar");
                    

                    //figure out what format the PDB archive has been uploaded in
                    if (!(mime_type.equals("application/x-tar")
                            || mime_type.equals("application/zip"))) {

                            //if it's not tar or zip, its error page for you sonny jim!
                            out.println("<html>");
                            out.println("<meta http-equiv=\"refresh\" content=\"0; url=error.jsp?errorcode=3\">");
                            out.println("</html>");

                    } else {

                        //file is a tar or a zip, keep going

                        //extract the PDB archive
                        PXArchiveUtils.extractArchive(pdb_file, mime_type, pdbs_temp_dir, true);

                        //create an ArrayList to store our PDBs in
                        ArrayList pdbs = new ArrayList<String>();
                        
                        //cycle the pdbs and add them to the ArrayList
                        //this strips out any extra crap uploaded in the archive
                        File[] tempFiles = tempDir.listFiles();

                        for (int i = 0; i < tempFiles.length; i++) {
                            if (tempFiles[i].getName().endsWith(".pdb")) {
                                pdbs.add(tempFiles[i].getName());
                            }
                        } //end for loop of tempFiles


                        //grab the values of user input
                        String f_label = multi.getParameter("flabel");
                        String sigf_label = multi.getParameter("sigflabel");
                        double mol_weight = Double.parseDouble(multi.getParameter("molWeight"));
                        int number_in_au = Integer.parseInt(multi.getParameter("numberInAU"));
                        int packing = Integer.parseInt(multi.getParameter("packing"));
                        int number_of_copies_to_search_for = Integer.parseInt(multi.getParameter("numberOfCopiesToSearchFor"));
                        String[] space_groups = multi.getParameterValues("spacegroups[]");
                        String[] rmsd_values = multi.getParameterValues("rmsdValue[]");
                        String grid_name = multi.getParameter("grid");

                        //try submitting
                        try {
                            submission_id =
                                    this.submissionController.processSubmission(
                                                        mtz_file,
                                                        mtz_temp_dir,
                                                        pdbs,
                                                        pdbs_temp_dir,
                                                        space_groups, 
                                                        rmsd_values,
                                                        f_label,
                                                        sigf_label,
                                                        mol_weight, 
                                                        number_in_au, 
                                                        number_of_copies_to_search_for, 
                                                        packing, 
                                                        grid_name, 
                                                        "xgrid"); //hard coded to "xgrid" for now.



                        } catch (Exception ex) {
                            
                            //if we couldn't submit, go to error page
                            //special error pages depending on the exception returned
                            
                            //PDB files don't exist
                            if(ex.getMessage().contains("PDB file ") && ex.getMessage().contains("does not exist")) {
                                
                                out.println("<html>");
                                out.println("<meta http-equiv=\"refresh\" content=\"0; url=error.jsp?errorcode=8\">");
                                out.println("</html>");
                            }
                            
                            //Directories couldn't be created
                            if(ex.getMessage().contains("directories")) {
                                out.println("<html>");
                                out.println("<meta http-equiv=\"refresh\" content=\"0; url=error.jsp?errorcode=9\">");
                                out.println("</html>");
                            }
                            
                            //couldn't move MTZ from it's temp location
                            if(ex.getMessage().contains("Could not move MTZ File")) {
                                out.println("<html>");
                                out.println("<meta http-equiv=\"refresh\" content=\"0; url=error.jsp?errorcode=10\">");
                                out.println("</html>");
                            }
                            
                            //couldn't move PDB file from it's temp location
                            if(ex.getMessage().contains("Could not move PDB File")) {
                                out.println("<html>");
                                out.println("<meta http-equiv=\"refresh\" content=\"0; url=error.jsp?errorcode=11\">");
                                out.println("</html>");
                            }
                            
                            //generic error
                            out.println("<html>");
                            out.println("<meta http-equiv=\"refresh\" content=\"0; url=error.jsp?errorcode=1\">");
                            out.println("</html>");
                        }

                        //submission id is null, go to error page
                        if(submission_id == null) {
                            out.println("<html>");
                            out.println("<meta http-equiv=\"refresh\" content=\"0; url=error.jsp?errorcode=2\">");
                            out.println("</html>");
                        } else {
                        
                            //it worked, print a summary of the submission,
                            //with a results access url.
                            
                            out.println("<html>" +
                                        "   <head>" +
                                        "       <title>MRGrid Submission Info</title>" +
                                        "       <link href=\"styles/pxgrid_style.css\" rel=\"stylesheet\" type=\"text/css\" />" +
                                        "   </head>" +
                                        "   <body>" +
                                        "       <div id=\"logo\">" +
                                        "           <h1><a href=\"mrgrid.jsp\">MRGrid</a></h1><br/>" +
                                        "           <h2>Distributed Molecular Replacement</h2>" +
                                        "       </div>" +
                                        "       <div id=\"page\">" +
                                        "           <div id=\"menu\">" +
                                        "               <ul>" +
                                        "                   <li><a href=\"mrgrid.jsp\">New Submission</a></li>" +
                                        "               </ul>" +
                                        "           </div>" +
                                        "           <div id=\"blurb\">" +
                                        "           <p>MRGrid allows you to perform Molecular Replacement (MR) calculations in parallel by making use of <a href=\"http://www-structmed.cimr.cam.ac.uk/phaser/\">Phaser</a> and <a href=\"http://www.apple.com/server/macosx/technology/xgrid.html\">Apple's Xgrid</a> technology." +
                                        "           <br/>Each Phaser job is submitted to an agent of an Xgrid. This means that, depending on the number of Xgrid nodes available, tens to hundreds of search models and space groups can be tested in parallel, saving considerable time.</p>" +
                                        "           </div>" +
                                        "           <div id=\"content\">" +
                                        "               <h1 class=\"title\">Submission Details</h1>" +
                                        "               <p>Your submission has been successfully sent to the Xgrid. " +
                                        "               <br/>You can view the results of your submission at: <a href=\"results.jsp?id="+submission_id+"\">results.jsp?id="+submission_id+"</a>" +
                                        "               <div id=\"MTZFormSection\" class=\"formSection\">" +
                                        "                   <div id=\"MTZFormSectionHeader\" class=\"formSectionHeader\">MTZ File Details</div>" +
                                        "                   <div id=\"MTZFormSectionContent\" class=\"formSectionContent\">" +
                                        "                           <span class=\"variableLabel\">MTZ File:</span> " + mtz_file + "<br/><br/>" +
                                        "                           <span class=\"variableLabel\">F Label:</span> " + f_label + "<br/><br/>" +
                                        "                           <span class=\"variableLabel\">SIGF Label:</span> " + sigf_label + "<br/><br/>" +
                                        "                           <span class=\"variableLabel\">Molecular Weight:</span> " + mol_weight + "<br/><br/>" +
                                        "                           <span class=\"variableLabel\">Number in asymmetric unit:</span> " + number_in_au + "<br/><br/>" +
                                        "                           <span class=\"variableLabel\">Space Groups to search within:</span><br/>");

                            for (int i = 0; i < space_groups.length; i++) {
                                out.println(String.valueOf(space_groups[i]) + "<br/>");
                            }

                            out.println("                           <br/>" +
                                        "                           <span class=\"variableLabel\">PDB Search Ensembles:</span><br/>");

                            for (int i = 0; i < pdbs.size(); i++) {
                                out.println(String.valueOf(pdbs.get(i)) + "<br/>");
                            }

                            out.println("                           <br/>" +
                                        "                           <span class=\"variableLabel\">Packing:</span> " + packing +
                                        "                           <br/>" +
                                        "                           <br/>" +
                                        "                           <span class=\"variableLabel\">Number of copies to search for:</span> " + number_of_copies_to_search_for +
                                        "                           <br/>" +
                                        "                           <br/>" +
                                        "                           <span class=\"variableLabel\">RMSD values to search:</span><br/>");

                            for (int i = 0; i < rmsd_values.length; i++) {
                                out.println(rmsd_values[i] + "<br/>");
                            }

                            out.println("                           <br/>" +
                                        "                           <br/>" +
                                        "                   </div>" +
                                        "               </div>" +
                                        "           </div>" +
                                        "       </div>" +
                                        "   </body>" +
                                        "</html>");

                        }


                    } //end else (PDB is x-tar)
                } //end else (PDB Tar exists)

            } //end else (MTZ file exists)

        } catch (IOException ex) {

            out.println("<html>");
            out.println("<meta http-equiv=\"refresh\" content=\"0; url=error.jsp?errorcode=0\">");
            out.println("</html>");

        } finally {
            out.close();
        }
    }


    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

//    /** 
//     * Returns a short description of the servlet.
//     */
//    public String getServletInfo() {
//        return "Short description";
//    }
//    // </editor-fold>
//    private HashMap extractColumnFLabelsFromMTZFile(String filename) {
//        String mtz_string = PXUtils.fileToString(filename);
//        HashMap labels = new HashMap();
//
//        String[] mtz_array = mtz_string.split("COLUMN");
//
//        for (int i = 0; i < mtz_array.length; i++) {
//            if (mtz_array[i].toString().contains("  F  ")) {
//
//                String fString = mtz_array[i].toString().trim();
//                labels.put(i, fString.substring(0, fString.indexOf(" ")));
//            }
//        }
//        return labels;
//    }

}
